package cn.tradewin.pmp.pages.master;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Log;
import org.apache.tapestry5.annotations.PageLoaded;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.BeanModelSource;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;

import cn.tradewin.common.model.SelectOption;
import cn.tradewin.common.util.SelectModelUtil;
import cn.tradewin.pmp.persist.model.MDept;
import cn.tradewin.pmp.services.DeptManageService;

@Import(stack={"core"})
public class DeptManage {

	@Property
	private final DeptEncoder deptEncoder = new DeptEncoder();

	@Property
	private final DateEncoder dateEncoder = new DateEncoder();

	@Property
	List<MDept> depts;

	@Property
	private MDept dept;
	
	@Property
	private MDept updDept;

	private MDept current;

	private boolean inFormSubmission;

	private List<MDept> deptsSubmitted;

	@Property
	private SelectModelUtil empModel;

	@Inject
	private DeptManageService deptService;

	@Inject
	private BeanModelSource beanModelSource;
	
	@Property
	private BeanModel<MDept> beanModel;

	@Inject
	private Messages messages;
	
	@Inject
	private ComponentResources resources;
	
	@Environmental
	private JavaScriptSupport js;
	
	@Inject
	Logger log;
	
	@PageLoaded
	void PageLoaded() {
		List<SelectOption> emps = new ArrayList<SelectOption>();
		for (int i = 0; i < 5; i++) {
			SelectOption e = new SelectOption("emp" + i, String.valueOf(i));
			emps.add(e);
		}
		empModel = new SelectModelUtil(emps);
	}
	
	@Log
	void onActivate() {
		inFormSubmission = false;
	}

	@Log
	void setupRender() {
		beanModel = beanModelSource.createDisplayModel(MDept.class, messages);
		beanModel.add("update", null);
		beanModel.include("selected", "deptNo", "deptName", "ministerNo", "updateDatetime", "update");
		beanModel.get("selected").label("");
		beanModel.get("selected").sortable(false);
		beanModel.get("deptNo").sortable(false);
		beanModel.get("deptName").sortable(false);
		beanModel.get("ministerNo").sortable(false);
		beanModel.get("updateDatetime").sortable(false);
		beanModel.get("update").label("");
		beanModel.get("update").sortable(false);
	}

	@Log
	void beginRender() {
	}

	@Log
	Object onPassivate() {
		return null;
	}

	@Log
	void onPrepareForRender() {
		if (depts == null) {
			depts = deptService.getAllDepts();
		}
	}

	@Log
	void onPrepare() {
		if (dept == null) {
			dept = new MDept();
		}
		if (updDept == null) {
			updDept = new MDept();
		}
	}

	@Log
	void afterRender() {
		js.require("jquery");
		js.require("bootstrap");
		JSONObject params = new JSONObject();
		params.put("id", "deptList");
		log.debug("url = " + this.getPageLink());
		params.put("url", this.getPageLink());
		js.require("DeptManage").invoke("init").with(params);
	}

	@Log
	void cleanupRender() {

	}

	@Log
	void onPrepareForSubmit() {
		inFormSubmission = true;
		deptsSubmitted = new ArrayList<MDept>();
	}

	/**
	 * delete selected department
	 */
	@Log
	void onSuccessFromDeptListForm() {
		List<Integer> delDepts = new ArrayList<Integer>();
		for (MDept m : deptsSubmitted) {
			if (m.isSelected()) {
				delDepts.add(m.getDeptNo());
			}
		}
		if (delDepts.size() > 0) {
			deptService.DelDepts(delDepts);
		}
	}
	
	void onSuccessFromUpdForm() {
		try {
			log.debug("form url = " + getFormEventUrl());
			updDept.setUpdateDatetime(new Date());
//			updDept.setUpdateUser("zhouyc");
			deptService.updDept(updDept);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Log
	void onSuccessFromAddDeptment() {
		try {
			deptService.AddDept(dept);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Log
	JSONObject onUpdateDept(Integer deptNo) {
		ObjectMapper objectMapper = new ObjectMapper();
		updDept = deptService.findDeptByPrimary(deptNo);
		if (updDept != null) {
			try {
				return new JSONObject(objectMapper.writeValueAsString(updDept));
			} catch (JsonGenerationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (JsonMappingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}

	
	private String getPageLink() {
		Link link = resources.createEventLink("updateDept");
		return link.toAbsoluteURI();
	}
	
	
	private String getFormEventUrl() {
		Link link = resources.createFormEventLink("updForm");
		return link.toAbsoluteURI();
	}
	
	public MDept getCurrent() {
		return current;
	}

	public void setCurrent(MDept current) {
		this.current = current;
		if (inFormSubmission) {
			this.deptsSubmitted.add(current);
		}
	}
	
	private class DeptEncoder implements ValueEncoder<MDept> {

		public String toClient(MDept value) {
			return value.getDeptNo().toString();
		}

		public MDept toValue(String clientValue) {
			MDept m = new MDept();
			m.setDeptNo(Integer.parseInt(clientValue));
			return m;
		}
	}

	private class DateEncoder implements ValueEncoder<Date> {

		@Override
		public String toClient(Date date) {
			long timeMillis = date.getTime();
			return Long.toString(timeMillis);
		}

		@Override
		public Date toValue(String timeMillisAsString) {
			long timeMillis = Long.parseLong(timeMillisAsString);
			Date date = new Date(timeMillis);
			return date;
		}

	}

}
